package rexsee.content;

import rexsee.core.application.RexseeApplication;
import rexsee.core.browser.Browser;
import rexsee.core.browser.clazz.ActivityReturn;
import rexsee.core.browser.clazz.JavascriptInterface;
import rexsee.core.browser.clazz.SyncTask;
import rexsee.core.browser.clazz.SyncTask.StringRunnable;
import rexsee.core.utilities.Json;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.Relation;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.Settings;
import android.provider.ContactsContract.StatusUpdates;
import android.provider.ContactsContract.SyncState;

public class RexseeContacts implements JavascriptInterface {

	public static final String INTERFACE_NAME = "Contacts";
	@Override
	public String getInterfaceName() {
		return mBrowser.application.resources.prefix + INTERFACE_NAME;
	}
	@Override
	public JavascriptInterface getInheritInterface(Browser childBrowser) {
		return this;
	}
	@Override
	public JavascriptInterface getNewInterface(Browser childBrowser) {
		return new RexseeContacts(childBrowser);
	}

	private final Browser mBrowser;
	private final Context mContext;

	public RexseeContacts(Browser browser) {
		mBrowser = browser;
		mContext = browser.getContext();
	}
	public RexseeContacts(Context context) {
		mBrowser = null;
		mContext = context;
	}

	public static String getPhoneType(int type) {
		switch (type) {
			case Phone.TYPE_ASSISTANT :
				return "ASSISTANT";
			case Phone.TYPE_CALLBACK :
				return "CALLBACK";
			case Phone.TYPE_CAR :
				return "CAR";
			case Phone.TYPE_COMPANY_MAIN :
				return "COMPANY_MAIN";
			case Phone.TYPE_FAX_HOME :
				return "FAX_HOME";
			case Phone.TYPE_FAX_WORK :
				return "FAX_WORK";
			case Phone.TYPE_HOME :
				return "HOME";
			case Phone.TYPE_ISDN :
				return "ISDN";
			case Phone.TYPE_MAIN :
				return "MAIN";
			case Phone.TYPE_MMS :
				return "MMS";
			case Phone.TYPE_MOBILE :
				return "MOBILE";
			case Phone.TYPE_OTHER :
				return "OTHER";
			case Phone.TYPE_OTHER_FAX :
				return "OTHER_FAX";
			case Phone.TYPE_PAGER :
				return "PAGER";
			case Phone.TYPE_RADIO :
				return "RADIO";
			case Phone.TYPE_TELEX :
				return "TELEX";
			case Phone.TYPE_TTY_TDD :
				return "TTY_TDD";
			case Phone.TYPE_WORK :
				return "WORK";
			case Phone.TYPE_WORK_MOBILE :
				return "WORK_MOBILE";
			case Phone.TYPE_WORK_PAGER :
				return "WORK_PAGER";
			case Phone.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getEmailType(int type) {
		switch (type) {
			case Email.TYPE_HOME :
				return "HOME";
			case Email.TYPE_MOBILE :
				return "MOBILE";
			case Email.TYPE_OTHER :
				return "OTHER";
			case Email.TYPE_WORK :
				return "WORK";
			case Email.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getOrganizationType(int type) {
		switch (type) {
			case Organization.TYPE_OTHER :
				return "OTHER";
			case Organization.TYPE_WORK :
				return "WORK";
			case Organization.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getImType(int type) {
		switch (type) {
			case Im.TYPE_OTHER :
				return "OTHER";
			case Im.TYPE_WORK :
				return "WORK";
			case Im.TYPE_HOME :
				return "HOME";
			case Im.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getImProtocol(int protocol) {
		switch (protocol) {
			case Im.PROTOCOL_AIM :
				return "AIM";
			case Im.PROTOCOL_CUSTOM :
				return "CUSTOM";
			case Im.PROTOCOL_GOOGLE_TALK :
				return "GOOGLE_TALK";
			case Im.PROTOCOL_ICQ :
				return "ICQ";
			case Im.PROTOCOL_JABBER :
				return "JABBER";
			case Im.PROTOCOL_MSN :
				return "MSN";
			case Im.PROTOCOL_NETMEETING :
				return "NETMEETING";
			case Im.PROTOCOL_QQ :
				return "QQ";
			case Im.PROTOCOL_SKYPE :
				return "SKYPE";
			case Im.PROTOCOL_YAHOO :
				return "YAHOO";
			default :
				return "unknown";
		}
	}
	public static String getNicknameType(int type) {
		switch (type) {
			case Nickname.TYPE_DEFAULT :
				return "DEFAULT";
			case Nickname.TYPE_INITIALS :
				return "INITIALS";
			case Nickname.TYPE_MAINDEN_NAME :
				return "MAINDEN_NAME";
			case Nickname.TYPE_OTHER_NAME :
				return "OTHER_NAME";
			case Nickname.TYPE_SHORT_NAME :
				return "SHORT_NAME";
			case Nickname.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getPostalType(int type) {
		switch (type) {
			case StructuredPostal.TYPE_HOME :
				return "HOME";
			case StructuredPostal.TYPE_OTHER :
				return "OTHER";
			case StructuredPostal.TYPE_WORK :
				return "WORK";
			case StructuredPostal.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getWebsiteType(int type) {
		switch (type) {
			case Website.TYPE_BLOG :
				return "BLOG";
			case Website.TYPE_FTP :
				return "FTP";
			case Website.TYPE_HOME :
				return "HOME";
			case Website.TYPE_HOMEPAGE :
				return "HOMEPAGE";
			case Website.TYPE_OTHER :
				return "OTHER";
			case Website.TYPE_PROFILE :
				return "PROFILE";
			case Website.TYPE_WORK :
				return "WORK";
			case Website.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getEventType(int type) {
		switch (type) {
			case Event.TYPE_ANNIVERSARY :
				return "ANNIVERSARY";
			case Event.TYPE_BIRTHDAY :
				return "BIRTHDAY";
			case Event.TYPE_OTHER :
				return "OTHER";
			case Event.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}
	public static String getRelationType(int type) {
		switch (type) {
			case Relation.TYPE_ASSISTANT :
				return "ASSISTANT";
			case Relation.TYPE_BROTHER :
				return "BROTHER";
			case Relation.TYPE_CHILD :
				return "CHILD";
			case Relation.TYPE_DOMESTIC_PARTNER :
				return "DOMESTIC_PARTNER";
			case Relation.TYPE_FATHER :
				return "FATHER";
			case Relation.TYPE_FRIEND :
				return "FRIEND";
			case Relation.TYPE_MANAGER :
				return "MANAGER";
			case Relation.TYPE_MOTHER :
				return "MOTHER";
			case Relation.TYPE_PARENT :
				return "PARENT";
			case Relation.TYPE_PARTNER :
				return "PARTNER";
			case Relation.TYPE_REFERRED_BY :
				return "REFERRED_BY";
			case Relation.TYPE_RELATIVE :
				return "RELATIVE";
			case Relation.TYPE_SISTER :
				return "SISTER";
			case Relation.TYPE_SPOUSE :
				return "SPOUSE";
			case Relation.TYPE_CUSTOM :
				return "CUSTOM";
			default :
				return "unknown";
		}
	}

	private static final String[] DATA_CURSOR_COLUMNS = new String[]{
			Data.MIMETYPE, //0
			Data.CUSTOM_RINGTONE, //1
			Data.CONTACT_STATUS_TIMESTAMP, //2
			Data.STARRED, //3
			Data.TIMES_CONTACTED, //4
			Data.LAST_TIME_CONTACTED, //5
			"data1", "data2", "data3", "data4", "data5", "data6", "data7", "data8", "data9", "data10",
			//"data11", "data12", "data13", "data14", "data15",
			Groups.ACCOUNT_NAME, //16
			Data.DISPLAY_NAME //17
	};

	private String getGroupIdByName(String accountName, String groupName) {
		ContentResolver contentResolver = mContext.getContentResolver();
		Cursor cursor = contentResolver.query(Groups.CONTENT_URI, new String[]{Data._ID}, RawContacts.ACCOUNT_NAME + "=? AND " + Groups.TITLE + "=?", new String[]{accountName, groupName}, Data._ID + " limit 1");
		if (cursor == null || cursor.getCount() == 0) return null;
		cursor.moveToFirst();
		String id = cursor.getString(0);
		cursor.close();
		return id;
	}
	private String getGroupNameById(int groupId) {
		ContentResolver contentResolver = mContext.getContentResolver();
		Cursor cursor = contentResolver.query(Groups.CONTENT_URI, new String[]{Groups.TITLE}, Data._ID + "=?", new String[]{String.valueOf(groupId)}, Data._ID);
		if (cursor == null || cursor.getCount() == 0) return null;
		cursor.moveToFirst();
		String title = cursor.getString(0);
		cursor.close();
		return title;
	}
	private String queryContactsData(String selection) {
		Cursor cursor = null;
		ContentResolver contentResolver = mContext.getContentResolver();
		try {
			cursor = contentResolver.query(Data.CONTENT_URI, DATA_CURSOR_COLUMNS, selection, null, null);
			String rtn = queryContactsData(cursor);
			cursor.close();
			return rtn;
		} catch (Exception e) {
			return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
		}
	}
	private String queryContactsData(Cursor cursor) {
		if (cursor == null || cursor.getCount() == 0) return "{}";
		String rtn = "";
		String display_name = "", account = "", ringtone = "", names = "", phones = "", emails = "", organizations = "", ims = "", nicknames = "", postals = "", webs = "", events = "", relations = "", notes = "", groups = "";
		int times_contacted = 0;
		long last_time_contacted = -1;
		long last_time_updated = -1;
		boolean starred = false;
		for (int i = 0; i < cursor.getCount(); i++) {
			cursor.moveToPosition(i);
			if (cursor.getString(1) != null) ringtone = (ringtone.equals("")) ? "\"" + cursor.getString(1) + "\"" : ringtone + ",\"" + cursor.getString(1) + "\"";
			starred = starred || (cursor.getInt(3) == 1);
			times_contacted += cursor.getInt(4);
			last_time_updated = Math.max(last_time_updated, cursor.getInt(2));
			last_time_contacted = Math.max(last_time_contacted, cursor.getInt(5));
			if (cursor.getString(16) != null && !account.contains(cursor.getString(16))) account = (account.equals("")) ? "\"" + cursor.getString(16) + "\"" : account + ",\"" + cursor.getString(16) + "\"";
			if (cursor.getString(17) != null && !display_name.contains(cursor.getString(17))) display_name = (display_name.equals("")) ? "\"" + cursor.getString(17) + "\"" : display_name + ",\"" + cursor.getString(17) + "\"";
			String mimetype = cursor.getString(0);
			if (mimetype.equals(StructuredName.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"DISPLAY_NAME\":\"" + cursor.getString(6) + "\"";
				element += ",\"GIVEN_NAME\":\"" + cursor.getString(7) + "\"";
				element += ",\"FAMILY_NAME\":\"" + cursor.getString(8) + "\"";
				element += ",\"PREFIX\":\"" + cursor.getString(9) + "\"";
				element += ",\"MIDDLE_NAME\":\"" + cursor.getString(10) + "\"";
				element += ",\"SUFFIX\":\"" + cursor.getString(11) + "\"";
				//element += ",\"PHONETIC_GIVEN_NAME\":\"" + cursor.getString(12) + "\"";
				//element += ",\"PHONETIC_MIDDLE_NAME\":\"" + cursor.getString(13) + "\"";
				//element += ",\"PHONETIC_FAMILY_NAME\":\"" + cursor.getString(14) + "\"";
				element += "}";
				names = (names.equals("")) ? element : names + "," + element;
			} else if (mimetype.equals(Phone.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"NUMBER\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getPhoneType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += "}";
				phones = (phones.equals("")) ? element : phones + "," + element;
			} else if (mimetype.equals(Email.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"ADDRESS\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getEmailType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += "}";
				emails = (emails.equals("")) ? element : emails + "," + element;
			} else if (mimetype.equals(Photo.CONTENT_ITEM_TYPE)) {
			} else if (mimetype.equals(Organization.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"COMPANY\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getOrganizationType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += ",\"TITLE\":\"" + cursor.getString(9) + "\"";
				element += ",\"DEPARTMENT\":\"" + cursor.getString(10) + "\"";
				element += ",\"JOB_DESCRIPTION\":\"" + cursor.getString(11) + "\"";
				//element += ",\"SYMBOL\":\"" + cursor.getString(12) + "\"";
				//element += ",\"PHONETIC_NAME\":\"" + cursor.getString(13) + "\"";
				element += ",\"OFFICE_LOCATION\":\"" + cursor.getString(14) + "\"";
				element += "}";
				organizations = (organizations.equals("")) ? element : organizations + "," + element;
			} else if (mimetype.equals(Im.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"ADDRESS\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getImType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += ",\"PROTOCOL\":\"" + getImProtocol(cursor.getInt(10)) + "\"";
				element += ",\"CUSTOM_PROTOCOL\":\"" + cursor.getString(11) + "\"";
				element += "}";
				ims = (ims.equals("")) ? element : ims + "," + element;
			} else if (mimetype.equals(Nickname.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"NAME\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getNicknameType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += "}";
				nicknames = (nicknames.equals("")) ? element : nicknames + "," + element;
			} else if (mimetype.equals(Note.CONTENT_ITEM_TYPE)) {
				String element = "\"" + cursor.getString(6) + "\"";
				notes = (notes.equals("")) ? element : notes + "," + element;
			} else if (mimetype.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"ADDRESS\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getPostalType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += ",\"STREET\":\"" + cursor.getString(9) + "\"";
				element += ",\"POBOX\":\"" + cursor.getString(10) + "\"";
				element += ",\"NEIGHBORHOOD\":\"" + cursor.getString(11) + "\"";
				element += ",\"CITY\":\"" + cursor.getString(12) + "\"";
				element += ",\"REGION\":\"" + cursor.getString(13) + "\"";
				element += ",\"POSTCODE\":\"" + cursor.getString(14) + "\"";
				element += ",\"COUNTRY\":\"" + cursor.getString(15) + "\"";
				element += "}";
				postals = (postals.equals("")) ? element : postals + "," + element;
			} else if (mimetype.equals(GroupMembership.CONTENT_ITEM_TYPE)) {
				String element = "\"" + getGroupNameById(cursor.getInt(6)) + "\"";
				groups = (groups.equals("")) ? element : groups + "," + element;
			} else if (mimetype.equals(Website.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"URL\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getWebsiteType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += "}";
				webs = (webs.equals("")) ? element : webs + "," + element;
			} else if (mimetype.equals(Event.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"START_DATE\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getEventType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += "}";
				events = (events.equals("")) ? element : events + "," + element;
			} else if (mimetype.equals(Relation.CONTENT_ITEM_TYPE)) {
				String element = "{";
				element += "\"NAME\":\"" + cursor.getString(6) + "\"";
				element += ",\"TYPE\":\"" + getRelationType(cursor.getInt(7)) + "\"";
				element += ",\"LABEL\":\"" + cursor.getString(8) + "\"";
				element += "}";
				relations = (relations.equals("")) ? element : relations + "," + element;
			}
		}
		rtn += "\"display_name\":[" + display_name + "]";
		rtn += ",\"account\":[" + account + "]";
		rtn += ",\"group\":[" + groups + "]";
		rtn += ",\"last_time_updated\":" + last_time_updated;
		rtn += ",\"starred\":" + ((starred) ? "true" : "false");
		rtn += ",\"times_contacted\":" + times_contacted;
		rtn += ",\"last_time_contacted\":" + last_time_contacted;
		rtn += ",\"ringtone\":[" + ringtone + "]";
		rtn += ",\"name\":[" + names + "]";
		rtn += ",\"phone\":[" + phones + "]";
		rtn += ",\"email\":[" + emails + "]";
		rtn += ",\"organization\":[" + organizations + "]";
		rtn += ",\"im\":[" + ims + "]";
		rtn += ",\"nickname\":[" + nicknames + "]";
		rtn += ",\"postal\":[" + postals + "]";
		rtn += ",\"website\":[" + webs + "]";
		rtn += ",\"event\":[" + events + "]";
		rtn += ",\"relation\":[" + relations + "]";
		rtn += ",\"note\":[" + notes + "]";
		return "{" + rtn + "}";
	}

	//JavaScriptInterface

	public String getContentUris() {
		String rtn = "{";
		rtn += "\"Data\":\"" + Data.CONTENT_URI.toString() + "\"";
		rtn += ",\"RawContacts\":\"" + RawContacts.CONTENT_URI.toString() + "\"";
		rtn += ",\"Contacts\":\"" + Contacts.CONTENT_URI.toString() + "\"";
		rtn += ",\"Groups\":\"" + Groups.CONTENT_URI.toString() + "\"";
		rtn += ",\"StatusUpdates\":\"" + StatusUpdates.CONTENT_URI.toString() + "\"";
		rtn += ",\"AggregationExceptions\":\"" + AggregationExceptions.CONTENT_URI.toString() + "\"";
		rtn += ",\"Settings\":\"" + Settings.CONTENT_URI.toString() + "\"";
		rtn += ",\"SyncState\":\"" + SyncState.CONTENT_URI.toString() + "\"";
		rtn += ",\"PhoneLookup\":\"" + PhoneLookup.CONTENT_FILTER_URI.toString() + "\"";
		rtn += "}";
		return rtn;
	}

	public String getContactNames() {
		return getContactNames(null, null, false, false, true, true);
	}
	public String getContactNamesHasPhoneNumbers() {
		return getContactNames(null, null, true, false, true, true);
	}
	public String getStarredContactNames() {
		return getContactNames(null, null, false, true, true, true);
	}
	public String getContactNamesByAccount(final String accountName) {
		return getContactNames(accountName, null, false, false, true, true);
	}
	public String getContactNamesByGroup(final String accountName, final String groupName) {
		return getContactNames(accountName, groupName, false, false, true, true);
	}
	public String getContactNames(final String account, final String group, final boolean mustHasPhoneNumber, final boolean mustStarred, boolean showProgress, boolean cancelable) {
		StringRunnable runnable = new StringRunnable() {
			@Override
			public String run() {
				try {
					ContentResolver contentResolver = mContext.getContentResolver();
					Cursor cursor;
					Uri uri;
					String selection = "";
					if (mustHasPhoneNumber) selection += Data.HAS_PHONE_NUMBER + "=1";
					if (mustStarred) selection += (selection.equals("")) ? Data.STARRED + "=1" : " AND " + Data.STARRED + "=1";
					String accountName = (account == null || account.equals("")) ? null : account;
					String groupName = (group == null || group.equals("")) ? null : group;
					if (accountName != null && groupName != null) {
						uri = Data.CONTENT_URI;
						String groupId = getGroupIdByName(accountName, groupName);
						if (groupId == null) return RexseeApplication.EXCEPTION_PREFIX + "Group not found.";
						if (!selection.equals("")) selection += " AND ";
						selection += CommonDataKinds.GroupMembership.GROUP_ROW_ID + "='" + groupId + "' AND " + Data.MIMETYPE + "='" + CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE + "'";
					} else if (accountName != null) {
						uri = RawContacts.CONTENT_URI;
						if (!selection.equals("")) selection += " AND ";
						selection += RawContacts.ACCOUNT_NAME + "='" + accountName + "'";
					} else if (groupName != null) {
						return RexseeApplication.EXCEPTION_PREFIX + "Account name couldn't be null when groupName is not null.";
					} else {
						uri = Contacts.CONTENT_URI;
						if (selection.equals("")) selection = null;
						cursor = contentResolver.query(Contacts.CONTENT_URI, new String[]{Data.DISPLAY_NAME}, null, null, Data.DISPLAY_NAME);
					}
					cursor = contentResolver.query(uri, new String[]{Data.DISPLAY_NAME}, selection, null, Data.DISPLAY_NAME);
					String rtn = Json.toJson(cursor, 0);
					cursor.close();
					return rtn;
				} catch (Exception e) {
					return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
				}
			}
		};
		if (showProgress) {
			return new SyncTask().run(runnable, mBrowser, cancelable);
		} else {
			return new SyncTask().run(runnable, null, false);
		}
	}

	public String getGroupNames() {
		return getGroupNamesByAccount(null);
	}
	public String getGroupNamesByAccount(final String accountName) {
		try {
			ContentResolver contentResolver = mContext.getContentResolver();
			Cursor cursor;
			if (accountName != null) {
				cursor = contentResolver.query(Groups.CONTENT_URI, new String[]{Groups.TITLE}, RawContacts.ACCOUNT_NAME + "=?", new String[]{accountName}, Groups.TITLE);
			} else {
				cursor = contentResolver.query(Groups.CONTENT_URI, new String[]{Groups.TITLE}, null, null, Groups.TITLE);
			}
			String rtn = Json.toJson(cursor, 0);
			cursor.close();
			return rtn;
		} catch (Exception e) {
			return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
		}
	}

	public String getContact(final String contactName) {
		return getContact(null, contactName, true, true);
	}
	public String getContact(final String accountName, final String contactName, boolean showProgress, boolean cancelable) {
		String selection;
		if (accountName == null || accountName.equals("")) {
			selection = Data.DISPLAY_NAME + "='" + contactName + "'";
		} else {
			selection = RawContacts.ACCOUNT_NAME + "='" + accountName + "' AND " + Data.DISPLAY_NAME + "='" + contactName + "'";
		}
		return getContactData(selection, showProgress, cancelable);
	}

	public String getContactByPhone(final String phoneNumber) {
		return getContactByPhone(null, phoneNumber, true, true);
	}
	public String getContactByPhone(final String accountName, final String phoneNumber, boolean showProgress, boolean cancelable) {
		String selection;
		if (accountName == null || accountName.equals("")) {
			selection = Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "' AND data1='" + phoneNumber + "'";
		} else {
			selection = RawContacts.ACCOUNT_NAME + "='" + accountName + "' AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "' AND data1='" + phoneNumber + "'";
		}
		return getContactData(selection, showProgress, cancelable);
	}

	public String getContactData(final String selection, boolean showProgress, boolean cancelable) {
		StringRunnable runnable = new StringRunnable() {
			@Override
			public String run() {
				return queryContactsData(selection);
			}
		};
		if (showProgress) {
			return new SyncTask().run(runnable, mBrowser, cancelable);
		} else {
			return new SyncTask().run(runnable, null, false);
		}
	}

	public String getContactDataColumns() {
		return RexseeContent.getContentColumns_(mContext, Data.CONTENT_URI);
	}

	public String selectContact() {
		Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
		intent.setType(Phone.CONTENT_ITEM_TYPE);
		ActivityReturn activityReturn = new SyncTask().runActivity(intent, mBrowser);
		if (activityReturn.resultCode == Activity.RESULT_OK) {
			Cursor cursor = null;
			ContentResolver contentResolver = mContext.getContentResolver();
			try {
				cursor = contentResolver.query(activityReturn.resultIntent.getData(), DATA_CURSOR_COLUMNS, null, null, Data._ID + " limit 1");
				String rtn = queryContactsData(cursor);
				cursor.close();
				return rtn;
			} catch (Exception e) {
				return RexseeApplication.EXCEPTION_PREFIX + e.getLocalizedMessage();
			}
		} else {
			return RexseeApplication.EXCEPTION_PREFIX + "Failure code.";
		}
	}

}
